import java.io.*;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86136
 * Date: 2025-05-05
 * Time: 13:11
 */
public class TcpEchoServer {
    private ServerSocket serverSocket = null;
    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");

        //使用线程池--此处不建议使用newFixedThreadPool
        ExecutorService executor = Executors.newCachedThreadPool();
        while (true) {
            //每次客户端连接都会创建一个新的对象，每次客户端断开也就不再需要当前对象了,因此需要关闭资源，防止资源泄漏
            Socket clientSocket = serverSocket.accept();

            //使用多线程来调整
//            Thread t = new Thread(() -> {
//                possessConnection(clientSocket);
//            });
//            t.start();

            //使用线程池
            executor.submit(() -> {
               possessConnection(clientSocket);
            });
        }
    }

    private void possessConnection(Socket clientSocket){
        System.out.printf("[%s:%s] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()) {
            Scanner scanner = new Scanner(inputStream);
            PrintWriter writer = new PrintWriter(outputStream);
            while(true) {
                //1.读取请求并解析，可以使用read 也可以直接使用Scanner
                if(!scanner.hasNext()) {
                    System.out.printf("[%s:%d} 客户端下线!\n",clientSocket.getInetAddress(),
                                                            clientSocket.getPort());
                    break;
                }
                String request = scanner.next();

                //2.根据请求计算响应
                String response = process(request);

                //3.将响应返回给客户端
//                outputStream.write(request.getBytes());
                //这个操作只是把数据放到“发送缓冲区"，并没有真正写入网卡
                //暗暗约定一个请求/响应使用\n作为结束标记
                writer.println(request);
                //flush方法用来“冲刷缓冲区”
                writer.flush();
                //使用PrintWriter的行为，不进行套壳就可以直接发送

                //4.打印日志
                System.out.printf("[%s:%d] req:%s resp:%s\n", clientSocket.getInetAddress(),
                                    clientSocket.getPort(), request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //每次客户端连接都会创建一个新的对象，每次客户端断开也就不再需要当前对象了,因此需要关闭资源，防止资源泄漏
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}
